import * as nodeOsUtils from 'node-os-utils';
import * as si from 'systeminformation';
import { getLogger } from '@/utils/logger';
import monitorConfig from '@/config/monitor';
import { EventEmitter } from 'events';

// 创建常规日志记录器（不输出到控制台）
const logger = getLogger('metric-service', {
  console: false
});
// 创建控制台日志记录器
const consoleLogger = getLogger('metric-service');

// 创建事件发射器，用于发送告警事件
export const monitorEvents = new EventEmitter();

/**
 * 系统指标收集服务
 * 负责收集系统各项基本指标
 */
class MetricService {
  // 告警相关变量
  private lastAlertTime: Record<string, number> = {};
  
  /**
   * 构造函数
   */
  constructor() {
    try {
      if (monitorConfig.server.enabled) {
        // 定时收集指标
        this.setupCollectors();
        consoleLogger.info('指标收集服务已初始化');
      } else {
        consoleLogger.info('指标收集服务已禁用');
      }
    } catch (error) {
      consoleLogger.error(`初始化指标收集服务失败: ${error instanceof Error ? error.message : String(error)}`);
      // 构造函数通常不抛出异常，避免影响系统启动
    }
  }
  
  /**
   * 设置定时收集器
   */
  private setupCollectors(): void {
    try {
      logger.debug('设置系统指标定时收集器');
      
      // 系统资源指标收集
      setInterval(async () => {
        await this.collectSystemMetrics();
      }, monitorConfig.server.collectInterval);
      
      logger.info(`系统指标定时收集器设置完成, 收集间隔: ${monitorConfig.server.collectInterval}ms`);
    } catch (error) {
      consoleLogger.error(`设置定时收集器失败: ${error instanceof Error ? error.message : String(error)}`);
      // 私有辅助方法，不抛出异常
    }
  }
  
  /**
   * 收集系统资源指标
   */
  private async collectSystemMetrics(): Promise<void> {
    try {
      logger.debug('开始收集系统资源指标');
      
      // 收集CPU使用率
      const cpuUsage = await nodeOsUtils.cpu.usage();
      
      // 检查CPU告警
      if (monitorConfig.alert.enabled && cpuUsage > monitorConfig.alert.thresholds.cpuUsage) {
        logger.debug(`CPU使用率超过阈值: ${cpuUsage.toFixed(2)}%, 阈值: ${monitorConfig.alert.thresholds.cpuUsage}%`);
        this.triggerAlert('cpu', `CPU使用率过高：${cpuUsage.toFixed(2)}%`, { value: cpuUsage });
      }
      
      // 收集内存使用情况
      const memory = await si.mem();
      
      const memoryUsagePercent = (memory.active / memory.total) * 100;
      
      // 检查内存告警
      if (monitorConfig.alert.enabled && memoryUsagePercent > monitorConfig.alert.thresholds.memoryUsage) {
        logger.debug(`内存使用率超过阈值: ${memoryUsagePercent.toFixed(2)}%, 阈值: ${monitorConfig.alert.thresholds.memoryUsage}%`);
        this.triggerAlert('memory', `内存使用率过高：${memoryUsagePercent.toFixed(2)}%`, { 
          value: memoryUsagePercent,
          used: memory.active,
          total: memory.total 
        });
      }
      
      // 收集磁盘使用情况
      const fsSize = await si.fsSize();
      for (const fs of fsSize) {
        const diskUsagePercent = (fs.used / fs.size) * 100;
        
        // 检查磁盘告警
        if (monitorConfig.alert.enabled && diskUsagePercent > monitorConfig.alert.thresholds.diskUsage) {
          logger.debug(`磁盘使用率超过阈值 ${fs.mount}: ${diskUsagePercent.toFixed(2)}%, 阈值: ${monitorConfig.alert.thresholds.diskUsage}%`);
          this.triggerAlert('disk', `磁盘使用率过高 ${fs.mount}: ${diskUsagePercent.toFixed(2)}%`, { 
            value: diskUsagePercent,
            mount: fs.mount,
            used: fs.used,
            total: fs.size 
          });
        }
      }
      
      logger.info('系统资源指标收集完成');
    } catch (error) {
      consoleLogger.error(`收集系统指标失败: ${error instanceof Error ? error.message : String(error)}`);
      // 私有辅助方法，不抛出异常
    }
  }
  
  /**
   * 记录HTTP请求
   * @param method HTTP方法
   * @param route 路由路径
   * @param statusCode 响应状态码
   * @param duration 请求处理时间（毫秒）
   */
  public recordHttpRequest(method: string, route: string, statusCode: number, duration: number): void {
    try {
      consoleLogger.info(`记录HTTP请求: ${method} ${route}, 状态码: ${statusCode}, 耗时: ${duration}ms`);
      
      const durationInSeconds = duration / 1000;
      
      // 检查响应时间是否超过阈值
      if (monitorConfig.alert.enabled && durationInSeconds * 1000 > monitorConfig.alert.thresholds.responseTime) {
        logger.debug(`请求响应时间超过阈值: ${durationInSeconds.toFixed(2)}秒, 阈值: ${monitorConfig.alert.thresholds.responseTime}ms`);
        this.triggerAlert('response_time', `请求响应时间过长：${durationInSeconds.toFixed(2)}秒`, {
          value: durationInSeconds * 1000,
          method,
          route,
          statusCode
        });
      }
      
      logger.info(`HTTP请求记录完成: ${method} ${route}`);
    } catch (error) {
      consoleLogger.error(`记录HTTP请求失败: ${error instanceof Error ? error.message : String(error)}`);
      // 虽然是公共方法，但此方法主要用于记录信息，不抛出异常以避免影响主流程
    }
  }
  
  /**
   * 触发告警
   * @param type 告警类型
   * @param message 告警消息
   * @param data 告警相关数据
   */
  private triggerAlert(type: string, message: string, data: any): void {
    try {
      const now = Date.now();
      const lastAlert = this.lastAlertTime[type] || 0;
      const cooldownMs = monitorConfig.alert.thresholds.cooldown * 60 * 1000;
      
      // 检查是否在冷却期
      if (now - lastAlert < cooldownMs) {
        logger.debug(`告警冷却中: 类型=${type}, 距离上次告警=${Math.floor((now - lastAlert) / 1000)}秒, 冷却时间=${monitorConfig.alert.thresholds.cooldown}分钟`);
        return;
      }
      
      // 更新最后告警时间
      this.lastAlertTime[type] = now;
      
      // 记录告警日志
      consoleLogger.warn(`触发系统告警 [${type}]: ${message}`, data);
      
      // 触发告警事件
      monitorEvents.emit('alert', {
        type,
        message,
        data,
        timestamp: now
      });
      
      logger.info(`告警事件已发送: 类型=${type}`);
    } catch (error) {
      consoleLogger.error(`触发告警失败: ${error instanceof Error ? error.message : String(error)}`);
      // 私有辅助方法，不抛出异常
    }
  }
}

// 导出单例实例
export default new MetricService(); 